package com.xbongbong.pro.message.service.impl;/*/*/

import com.alibaba.fastjson.JSON;
import com.xbongbong.message.domain.entity.PushEntity;
import com.xbongbong.message.domain.entity.PushLinkEntity;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DateEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.PaasDateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.message.enums.MessageGroupTypeEnum;
import com.xbongbong.pro.message.enums.MessageListSearchFilterMenuTagEnum;
import com.xbongbong.pro.message.enums.MessageListSearchFilterStatusTagEnum;
import com.xbongbong.pro.message.enums.MessageListSearchFilterTimeTagEnum;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.enums.RefEntityEnum;
import com.xbongbong.pro.message.model.PushLinkModel;
import com.xbongbong.pro.message.model.PushModel;
import com.xbongbong.pro.message.pojo.dto.MessageCountDTO;
import com.xbongbong.pro.message.pojo.dto.MessageReadAllDTO;
import com.xbongbong.pro.message.pojo.dto.MessageReadDTO;
import com.xbongbong.pro.message.pojo.vo.MessageCountVO;
import com.xbongbong.pro.message.pojo.vo.MessageReadAllVO;
import com.xbongbong.pro.message.pojo.vo.MessageReadVO;
import com.xbongbong.pro.message.service.PushLinkService;
import com.xbongbong.saas.constant.BasicConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Description: pushLinkService 实现
 * @author 李杰
 * @date 2019/1/15 11:10
 * @version v1.0
 * @since v1.0
 */
@Service("PushLinkService")
public class PushLinkServiceImpl implements PushLinkService {

    private static final Logger LOG = LoggerFactory.getLogger(PushLinkServiceImpl.class);

    @Resource
    private PushLinkModel pushLinkModel;

    @Resource
    private PushModel pushModel;


    /**
     * 解析 推送消息实体 插入推送消息关联表
     * @param push 推送消息实体
     */
    @Override
    public void insert(PushEntity push) {
        ArrayList<PushLinkEntity> pushLinkList = new ArrayList<>();
        pushLinkList = insertPush2PushLinkList(push, pushLinkList);
        if (pushLinkList.size() == 0) {
            return;
        }
        pushLinkModel.insertBatch(pushLinkList);
    }

    /**
     * 解析 推送消息实体队列 插入推送消息关联表
     * @param pushList 推送消息实体队列
     */
    @Override
    public void insertBatch(List<PushEntity> pushList) {
        ArrayList<PushLinkEntity> pushLinkList = new ArrayList<>();
        for (PushEntity push : pushList) {
            pushLinkList = insertPush2PushLinkList(push, pushLinkList);
        }
        if (pushLinkList.size() == 0) {
            return;
        }
        pushLinkModel.insertBatch(pushLinkList);
    }

    /**
     * 解析 推送消息实体 PushEntity 插入推送消息关联队列
     * @param push 消息
     * @param pushLinkList 消息关联队列
     * @return 插入的消息关联队列
     */
    @Override
    public ArrayList<PushLinkEntity> insertPush2PushLinkList(PushEntity push, ArrayList<PushLinkEntity> pushLinkList) {
        String pushObject = push.getPushObject();
        if (StringUtil.isEmpty(pushObject)) {
            return pushLinkList;
        }
        List<String> userIdList = JSON.parseArray(pushObject, String.class);
        userIdList = new ArrayList<>(new HashSet<>(userIdList));
        for (String userId : userIdList) {
            PushLinkEntity pushLink = new PushLinkEntity(push.getCorpid(), userId, push.getId(),
                    push.getRefEntity(), push.getRefId(), push.getIsRemind(), push.getPushTime());
            pushLinkList.add(pushLink);
        }
        return pushLinkList;
    }

    /**
     * 根据 pushId 查找推送的信息实体
     * @param pushIdInList 消息Push表ID
     * @return 消息队列
     */
    @Override
    public List<PushEntity> findPushList(List<Long> pushIdInList, String corpid) {
        Map<String, Object> param = new HashMap<>(16);
        param.put("pushIdIn", pushIdInList);
        param.put("corpid", corpid);
        return pushModel.findEntitys(param);
    }

    /**
     * Description: 获取用户未读消息总数(只包括及时消息)
     * @param messageCountDTO
     * @return MessageCountVO 符合查询条件的查询总数
     * @throws XbbException 数据库操作异常
     */
    @Override
    public MessageCountVO countUnread(MessageCountDTO messageCountDTO) throws XbbException {
        MessageCountVO messageCountVO = new MessageCountVO();
        String corpid = messageCountDTO.getCorpid();
        String userId = messageCountDTO.getUserId();
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Integer> refEntityList = MessageListSearchFilterMenuTagEnum.getRefEntityIdsById(0);
        try {
            params.put("corpid", corpid);
            params.put("userId", userId);
            params.put("isRead", 0);
            params.put("del", 0);
            params.put("isRemind", 0);
            params.put("refEntityIn", refEntityList);
            params.put("start", BasicConstant.ZERO);
            params.put("pageNum", 100);
            params.put("columns", "id");
            params.put("endPushTime", DateTimeUtil.getInt());
            // TODO message现在只汇总了SaaS消息，PaaS未做
            List<PushLinkEntity> pushLinkList =  pushLinkModel.findEntitys(params);
            Integer count = pushLinkList == null ? 0 : pushLinkList.size();
            // 上面进行分页，超过100条，也是返回100条
            messageCountVO.setCount(count);
            return messageCountVO;
        } catch (Exception e) {
            LOG.error("获取未读消息数失败");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 根据对象类型返回推送时间区间
     * 全部消息不显示将来提醒
     * @param params        查询参数
     * @param isRemind      跟进提醒
     * @param startPushTime 推送时间左截止
     * @param endPushTime   推送时间右截止
     * @return 封装后的查询参数
     */
    private Map<String, Object> getPushTimeBetween(Map<String, Object> params, Integer isRemind,
                                                   Integer startPushTime, Integer endPushTime) {
        if (isRemind != null && isRemind == 1) {
            // 跟进提醒显示未推送的数据
            params.put("isRemind", isRemind);
            if (startPushTime == null) {
                startPushTime = 0;
            }
            if (endPushTime == null) {
                // 显示接下来两年内的即将提醒
                endPushTime = DateUtil.getInt() + 63072000;
            }
        } else {
            if (startPushTime == null) {
                startPushTime = 0;
            }
            if (endPushTime == null) {
                endPushTime = DateUtil.getInt();
            }
        }
        params.put("startPushTime", startPushTime);
        params.put("endPushTime", endPushTime);
        return params;
    }


    @Override
    public MessageReadVO readPushList(MessageReadDTO messageReadDTO) throws XbbException{
        MessageReadVO messageReadVO = new MessageReadVO();
        Map<String, Object> param = new HashMap<>(16);
        param.put("idIn", messageReadDTO.getIds());
        Integer now = DateUtil.getInt();
        param.put("updateTime", now);
        param.put("endPushTime", now);
        param.put("corpid", messageReadDTO.getCorpid());
        pushLinkModel.readPushList(param);
        return messageReadVO;
    }

    /**
     * 删除消息Id队列的消息关联表
     * @param pushLinkIdList 消息关联列表
     */
    @Override
    public void deletePushList(List<Integer> pushLinkIdList, String corpid) {
        Map<String, Object> params = new HashMap<>(16);
        params.put("idIn", pushLinkIdList);
        Integer now = DateUtil.getInt();
        params.put("updateTime", now);
        params.put("corpid", corpid);
        pushLinkModel.deletePushList(params);
    }

    /**
     * 用户脱离团队后删除未发送的消息
     * @param corpid        公司id
     * @param userId        用户id
     * @param refEntityEnum 对象类型
     * @param refId         对象id
     */
    @Override
    public void apartTeam2DeleteMessage(String corpid, String userId, RefEntityEnum refEntityEnum, Integer refId) {
        Map<String, Object> params = new HashMap<>(16);
        params.put("corpid", corpid);
        params.put("userId", userId);
        params.put("refEntity", refEntityEnum.getCode());
        params.put("refId", refId);
        params.put("now", DateUtil.getInt());
        pushLinkModel.apartTeam2DeleteMessage(params);
    }

    /**
     * 用户脱离团队后删除未发送的消息
     *
     * @param corpid        公司id
     * @param userId        用户id
     * @param refEntityEnum 对象类型
     * @param refIdIn       对象id队列
     */
    @Override
    public void apartTeam2DeleteMessage(String corpid, String userId, RefEntityEnum refEntityEnum, List<Integer> refIdIn) {
        Map<String, Object> params = new HashMap<>(16);
        params.put("corpid", corpid);
        params.put("userId", userId);
        params.put("refEntity", refEntityEnum.getCode());
        params.put("refIdIn", refIdIn);
        params.put("now", DateUtil.getInt());
        pushLinkModel.apartTeam2DeleteMessage(params);
    }

    /**
     * Description: 标记用户全部未读信息为已读
     * @param messageReadAllDTO
     * @return MessageReadAllVO
     * @throws  XbbException 应用不存在
     */
    @Override
    public MessageReadAllVO readAllPushLink(MessageReadAllDTO messageReadAllDTO) throws XbbException {
        MessageReadAllVO messageReadAllVO = new MessageReadAllVO();
        String corpid = messageReadAllDTO.getCorpid();
        String userId = messageReadAllDTO.getUserId();
        Long appId = messageReadAllDTO.getAppId();
        Integer saasMark = messageReadAllDTO.getSaasMark();
        Integer isRemind = messageReadAllDTO.getIsRemind();
        Integer isDownload = messageReadAllDTO.getIsDownload();
        List<Integer> refEntitys = messageReadAllDTO.getRefEntity();
        Integer isRead = messageReadAllDTO.getStatusTags();
        Integer timeTag = messageReadAllDTO.getTimeTags();
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("corpid", corpid);
        params.put("userId", userId);
        if (Objects.equals(isRead, MessageListSearchFilterStatusTagEnum.READ.getId())) {
            params.put("isRead", 1);
        } else {
            params.put("isRead", 0);
        }
        try {
            List<Object> betweenTime = new ArrayList<>();
            if (Objects.equals(timeTag, MessageListSearchFilterTimeTagEnum.TODAY.getId())) {
                betweenTime = PaasDateUtil.computeTime(Collections.singletonList(DateEnum.TODAY.getValue()));
            } else if (Objects.equals(timeTag, MessageListSearchFilterTimeTagEnum.THIS_MONTH.getId())) {
                betweenTime = PaasDateUtil.computeTime(Collections.singletonList(DateEnum.THIS_MONTH.getValue()));
            } else if (Objects.equals(timeTag, MessageListSearchFilterTimeTagEnum.THIS_WEEK.getId())) {
                betweenTime = PaasDateUtil.computeTime(Collections.singletonList(DateEnum.THIS_WEEK.getValue()));
            }
            if (betweenTime.size() > 0) {
                params.put("startPushTime", betweenTime.get(0));
                params.put("endPushTime", betweenTime.get(1));
            }

            if (Objects.equals(isRemind, 1)) {
                params.put("isRemind", isRemind);
                pushLinkModel.readAllPushLink(params);
            } else if (Objects.equals(isDownload, 1)) {
                params.put("refEntityIn", Arrays.asList(PushTypeEnum.EXPORT_PUSH.getCode(), PushTypeEnum.EXPORT_PUSH_FAIL.getCode()));
                pushLinkModel.readAllPushLink(params);
            } else {
                if (Objects.equals(appId, 0L)) {
                    //全部消息一键已读，除了导出的消息
                    if (!Objects.equals(messageReadAllDTO.getPlatform(), PlatFormEnum.DINGTALK.getValue())) {
                        //dingtlak端有未推送提醒分组，一键已读提醒的也要已读,web端没有
                        params.put("isRemind", 0);
                    }
                    params.put("refEntityNotIn", Arrays.asList(PushTypeEnum.EXPORT_PUSH.getCode(), PushTypeEnum.EXPORT_PUSH_FAIL.getCode()));
                    pushLinkModel.readAllPushLink(params);
                } else {
                    if (Objects.equals(saasMark, SaasMarkEnum.SAAS.getCode())) {
                        List<Integer> refEntityList = MessageListSearchFilterMenuTagEnum.getRefEntityIdsById(appId.intValue());
                        if (refEntityList.size() == 0) {
                            //没有的直接不处理
                            return messageReadAllVO;
//                            throw new XbbException(ErrorCodeEnum.API_ERROR_300001);
                        }
                        if (refEntitys != null && refEntitys.size() > 0) {
                            refEntityList.retainAll(refEntitys);
                            params.put("refEntityIn", refEntityList);
                        } else {
                            params.put("refEntityIn", refEntityList);
                        }
                        if(Objects.equals(appId.intValue(), MessageGroupTypeEnum.DATA_CENTER.getCode())){
                            params.put("endPushTime",DateTimeUtil.getInt());
                        }
                        pushLinkModel.readAllPushLink(params);
                    } else if (Objects.equals(saasMark, SaasMarkEnum.PAAS.getCode())) {
                        //TODO message pass流程消息
                    }
                }

            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("一键已读失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        return new MessageReadAllVO();
    }

}
